package com.yopuo.pay.wxpay.server;

import com.yopuo.api.pay.model.Product;
import com.yopuo.api.pay.model.Result;
import com.yopuo.api.pay.wxpay.CpWxPayServer;
import com.yopuo.pay.wxpay.service.CpWxPayService;
import com.yopuo.pay.wxpay.util.HttpUtil;
import com.yopuo.pay.wxpay.util.PayCommonUtil;
import com.yopuo.pay.wxpay.util.WxPayUrl;
import com.yopuo.pay.wxpay.util.WxPayUtil;
import com.yopuo.pay.wxpay.util.XMLUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.ui.ModelMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * 微信支付
 *
 * 创建时间	2017年7月31日
 */
@Service
public class CpWxPayServerImpl implements CpWxPayServer {

	private static final Logger logger = LoggerFactory.getLogger(CpWxPayServerImpl.class);

    @Autowired
    private WxPayUtil wxPayUtil;
	@Autowired
	private CpWxPayService cpWxPayService;

    @Value("${wxPay.notify.url}")
    private String notifyUrl;

    @Value("${server.context.url}")
    private String serverUrl;


    /**
     * 方法描述: 二维码支付(模式一)根据商品ID预先生成二维码
     * @param: product
     * @param: map
     * @return: String
     * @author: zzh
     * @date: 2021/1/22
     */
	@Override
    public String  qcPay1(Product product, ModelMap map) {
		logger.info("二维码支付(模式一)");
        product.setProductId("20170721");
        cpWxPayService.wxPay1(product);
		String img= "../file/"+product.getProductId()+".png";
		map.addAttribute("img", img);
		return "wxPay/qcPay";
    }

	/**
	 * 方法描述: 二维码支付(模式二)下单并生成二维码
	 * @param: product
	 * @param: map
	 * @return: String
	 * @author: zzh
	 * @date: 2021/1/22
	 */
	@Override
    public String qcPay2(Product product, ModelMap map) {
		logger.info("二维码支付(模式二)");
        /**
         * 参数自定义  这只是个Demo
         */
		product.setProductId("20170721");
		product.setBody("两个苹果八毛钱 ");
		product.setSpbillCreateIp("192.168.1.66");
		Result result = cpWxPayService.wxPay2(product);
        if(Result.isOk(result)){
            String imageUrl = serverUrl + "/file/" +result.get("msg");
            logger.info("支付二维码地址：{}",imageUrl);
			map.addAttribute("img", imageUrl);
		}
		return "wxPay/qcPay";
    }

	/**
	 * 方法描述: 支付后台回调
	 * @param: request
	 * @return: response
	 * @author: zzh
	 * @date: 2021/1/22
	 */
	@Override
	public void notify(HttpServletRequest request, HttpServletResponse response){
		try {
			// 读取参数
			InputStream inputStream = request.getInputStream();
			StringBuffer sb = new StringBuffer();
			String s;
			BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
			while ((s = in.readLine()) != null) {
				sb.append(s);
			}
			in.close();
			inputStream.close();

			// 解析xml成map
			Map<String, String> m = XMLUtil.doXMLParse(sb.toString());
			// 过滤空 设置 TreeMap
			SortedMap<Object, Object> packageParams = new TreeMap<>();
			Iterator it = m.keySet().iterator();
			while (it.hasNext()) {
				String parameter = (String) it.next();
				String parameterValue = m.get(parameter);

				String v = "";
				if (null != parameterValue) {
					v = parameterValue.trim();
				}
				packageParams.put(parameter, v);
			}
			// 账号信息
			String key = wxPayUtil.wxPay().getApiKey(); // key
			// 判断签名是否正确
			if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) {
				logger.info("微信支付成功回调");
				// ------------------------------
				// 处理业务开始
				// ------------------------------
				String resXml = "";
				if ("SUCCESS".equals((String) packageParams.get("result_code"))) {
					// 这里是支付成功
					String orderNo = (String) packageParams.get("out_trade_no");
					logger.info("微信订单号{}付款成功",orderNo);
					//这里 根据实际业务场景 做相应的操作
					// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
					resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
				} else {
					logger.info("支付失败,错误信息：{}",packageParams.get("err_code"));
					resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
				}
				// ------------------------------
				// 处理业务完毕
				// ------------------------------
				BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
				out.write(resXml.getBytes());
				out.flush();
				out.close();
			} else {
				logger.info("通知签名验证失败");
			}
		}catch (Exception e){
			logger.info("微信支付回调通知失败:{}",e.getMessage());
		}
	}

	/**
	 * 方法描述: 模式一支付回调URL(生成二维码见 qrCodeUtil)
	 * 商户支付回调URL设置指引：进入公众平台-->微信支付-->开发配置-->扫码支付-->修改
	 * @author: zzh
	 * @date: 2021/1/22
	 */
	@Override
	public void bizpayurl(HttpServletRequest request, HttpServletResponse response) {
		logger.info("模式一支付回调URL");
		try {
			//读取参数
			InputStream inputStream = request.getInputStream();
			StringBuffer sb = new StringBuffer();
			String s;
			BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
			while ((s = in.readLine()) != null) {
				sb.append(s);
			}
			in.close();
			inputStream.close();

			//解析xml成map
			Map<String, String> map = XMLUtil.doXMLParse(sb.toString());
			//过滤空 设置 TreeMap
			SortedMap<Object, Object> packageParams = new TreeMap<>();
			Iterator it = map.keySet().iterator();
			while (it.hasNext()) {
				String parameter = (String) it.next();
				String parameterValue = map.get(parameter);

				String v = "";
				if (null != parameterValue) {
					v = parameterValue.trim();
				}
				packageParams.put(parameter, v);
			}
			//判断签名是否正确
			if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, wxPayUtil.wxPay().getApiKey())) {
				//统一下单
				SortedMap<Object, Object> params = new TreeMap<Object, Object>();
				wxPayUtil.commonParams(params);
				//随即生成一个 入库 走业务逻辑
				String out_trade_no=Long.toString(System.currentTimeMillis());
				params.put("body", "模式一扫码支付");// 商品描述
				params.put("out_trade_no", out_trade_no);// 商户订单号
				params.put("total_fee", "100");// 总金额
				params.put("spbill_create_ip", "192.168.1.66");// 发起人IP地址
				params.put("notify_url", notifyUrl);// 回调地址
				params.put("trade_type", "NATIVE");// 交易类型

				String paramsSign = PayCommonUtil.createSign("UTF-8", params, wxPayUtil.wxPay().getApiKey());
				params.put("sign", paramsSign);// 签名
				String requestXML = PayCommonUtil.getRequestXml(params);

				String resXml = HttpUtil.postData(WxPayUrl.UNIFIED_ORDER_URL, requestXML);
				Map<String, String>  payResult = XMLUtil.doXMLParse(resXml);
				String returnCode =  payResult.get("return_code");
				if("SUCCESS".equals(returnCode)){
					String resultCode = payResult.get("result_code");
					if("SUCCESS".equals(resultCode)){
						logger.info("(订单号：{}生成微信支付码成功)",out_trade_no);

						String prepay_id = payResult.get("prepay_id");
						SortedMap<Object, Object> prepayParams = new TreeMap<>();
						wxPayUtil.commonParams(params);
						prepayParams.put("prepay_id", prepay_id);
						prepayParams.put("return_code", "SUCCESS");
						prepayParams.put("result_code", "SUCCESS");
						String prepaySign =  PayCommonUtil.createSign("UTF-8", prepayParams, wxPayUtil.wxPay().getApiKey());
						prepayParams.put("sign", prepaySign);
						String prepayXml = PayCommonUtil.getRequestXml(prepayParams);

						//通知微信 预下单成功
						BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
						out.write(prepayXml.getBytes());
						out.flush();
						out.close();
					}else{
						String errCodeDes = map.get("err_code_des");
						logger.info("(订单号：{}生成微信支付码(系统)失败[{}])",out_trade_no,errCodeDes);
					}
				}else{
					String returnMsg = map.get("return_msg");
					logger.info("(订单号：{} 生成微信支付码(通信)失败[{}])",out_trade_no,returnMsg);
				}
			}else{
				logger.info("签名错误");
			}
		}catch (Exception e){
			logger.info("模式一支付回调通知失败：{}",e.getMessage());
		}

	}
}